/*
 * Wejp's Config File Parser
 *
 * File: wejpconfig.c
 * Version: 061102
 *
 * Copyright (c) 2003-2006 Johannes Heimansberg
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#define VERSION 20061102
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "wejpconfig.h"

/* Returns the complete path to ~/"filename" */
char *cfg_get_path_to_config_file(char *filename)
{
	char *home_directory, *path_to_config_file;

	home_directory = getenv("HOME");
	path_to_config_file = (char*)malloc((strlen(home_directory) + 
	                                     strlen(filename) + 2) * sizeof(char));
	sprintf(path_to_config_file, "%s/%s", home_directory, filename);
	return path_to_config_file;
}

/* Must be called before the first use of a ConfigFile struct element */
void cfg_init_config_file_struct(ConfigFile *cf)
{
	cf->lastkey = 0;
}

/* Checks wether the config file exists or not */
int cfg_check_config_file(char *filename)
{
	FILE *file;
	int  result = 0;
	file = fopen(filename, "r");
	if (file == NULL)
		result = -1;
	else
		fclose(file);
	return result;
}

/* Add a new key to the configuration */
int cfg_add_key(ConfigFile *cf, char *key, char *value)
{
	int result = 0;
	int strsize = 0;
	int i;
	
	if (cfg_get_key_value(*cf, key) != NULL) /* Key already exists->overwrite */
	{
		for (i = 0; i < cf->lastkey; i++)
			if (strncmp(key, cf->key[i], 127) == 0)
			{
				free(cf->key[i]); /* Free allocated memory */
				free(cf->value[i]);

				/* Allocate memory for the new string and save it... */
				strsize = (strlen(key) < 127 ? strlen(key) : 126) + 1;
				cf->key[i] = (char*)malloc(strsize * sizeof(char));
				sprintf(cf->key[i], "%s", key);

				strsize = (strlen(key) < 127 ? strlen(value) : 126) + 1;
				cf->value[i] = (char*)malloc(strsize * sizeof(char));
				sprintf(cf->value[i], "%s", value);
				break;
			}
	}
	else if (cf->lastkey < MAXKEYS)
	{
		strsize = (strlen(key) < 127 ? strlen(key) : 126) + 1;
		cf->key[cf->lastkey] = (char*)malloc(strsize * sizeof(char));
		sprintf(cf->key[cf->lastkey], "%s", key);

		strsize = (strlen(key) < 127 ? strlen(value) : 126) + 1;
		cf->value[cf->lastkey] = (char*)malloc(strsize * sizeof(char));
		sprintf(cf->value[cf->lastkey], "%s", value);
		
		(cf->lastkey)++;
	}
	else
		result = -1;
	return result;
}

/* Frees all memory allocated by read_config_file() */
void cfg_free_config_file_struct(ConfigFile *cf)
{
	int i;
	for (i = 0; i < cf->lastkey; i++)
	{
		free(cf->key[i]);
		free(cf->value[i]);
	}
	cf->lastkey = -1;
}

/* Loads a config file from disk */
int cfg_read_config_file(ConfigFile *cf, char *filename)
{
	FILE *file;
	char ch;
	int bufcnt;
	char key_buffer[128] = "", value_buffer[128] = "";

	/* parse config file and read keys+key values */
	file = fopen(filename, "r");
	if (file)
	{
		while(!feof(file))
		{
			ch = fgetc(file);
			/* Skip blanks... */
			if (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n')
				while (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n') ch = fgetc(file);
			/* ...and comments (#)... */
			do {
				if (ch == '#') {
					while (ch != '\n' && ch != '\r') ch = fgetc(file);
					ch = fgetc(file);
				}
				if (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r')
					ch = fgetc(file);
			} while (ch == '#' || ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r');

			bufcnt = 0;
			/* Read key name: */
			while (ch != ' ' && ch != '\t' && ch != '\n' && ch != '\r' && 
			       ch != '=' && !feof(file) && bufcnt < 126)
			{
				key_buffer[bufcnt] = ch;
				bufcnt++;
				ch = fgetc(file);
			}
			key_buffer[bufcnt] = '\0';

			while (ch != '=' && !feof(file))
			{
				ch = fgetc(file);
			}
			ch = fgetc(file);

			/* Skip blanks... */
			if (ch == ' ' || ch == '\t')
				while (ch == ' ' || ch == '\t') ch = fgetc(file);

			/* Read key value: */
			bufcnt = 0;
			while (ch != '\n' && ch != '\r' && !feof(file) && 
			       !feof(file) && bufcnt < 126)
			{
				value_buffer[bufcnt] = ch;
				bufcnt++;
				ch = fgetc(file);
			}
			value_buffer[bufcnt] = '\0';

			if (strlen(key_buffer) > 0)
				cfg_add_key(cf, key_buffer, value_buffer);
		}
		fclose(file);
	}
	else
	{
		printf("config: Cannot open config file!\n");
		return -2;
	}
	return 0;
}

/* Saves the configuration to file */
int cfg_write_config_file(ConfigFile *cf, char *filename)
{
	FILE *file;
	int  i = 0, result = 0;
	char buffer[256];
	file = fopen(filename, "w");
	if (file != NULL)
	{
		while (i < cf->lastkey)
		{
			snprintf(buffer, 255, "%s=%s\n", cf->key[i], cf->value[i]);
			fwrite(buffer, strlen(buffer) * sizeof(char), 1, file);
			i++;
		}
		fclose(file);
	}
	else
	{
		printf("config: failed opening %s\n", filename);
		result = -1;
	}
	return result;
}

/* Returns the value (as string) of "key" */
char *cfg_get_key_value(ConfigFile cf, char *key)
{
	char *result = NULL;
	int  i;
	
	for (i = 0; i < cf.lastkey; i++)
		if (strncmp(key, cf.key[i], 127) == 0)
		{
			result = cf.value[i];
			break;
		}
	return result;
}

int cfg_is_key_available(ConfigFile cf, char *key)
{
	int result = FALSE;
	int i;
	for (i = 0; i < cf.lastkey; i++)
		if (strncmp(key, cf.key[i], 127) == 0)
		{
			result = TRUE;
			break;
		}
	return result;	
}
